#include "logindialog.h"
#include "ui_logindialog.h"
#include "clickedlabel.h"
#include <QRegularExpression>
#include <QJsonObject>
#include "httpmgr.h"
#include "tcpmgr.h"
LoginDialog::LoginDialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::LoginDialog)
{
    ui->setupUi(this);

    //连接信号与信号
    connect(ui->register_button,&QPushButton::clicked,this,&LoginDialog::switchRegister);
    ui->pass_edit->setEchoMode(QLineEdit::Password);

    ui->forget_label->SetState("unvisible","unvisible_hover","","visible",
                               "visible_hover","");
    ui->forget_label->setCursor(Qt::PointingHandCursor);

    //clickLabelclick信号被触发的时候，会触发一个信号，由于是一个内部ui，外界不一定能够访问到，所以通过一层封装，保证外界
    //可以正常被一个内部组件的信号屏触发
    //内部ui组件的信号可以通过父组件信号进行转发：父组件创建一个信号与槽，父组件连接槽与内部UI的信号，父组件槽函数发出一个信号
    //外界就可以通过连接该信号，从而间接的被内部组件的信号触发
    //技巧：内部UI的信号，可以通过外部组件槽函数转发信号，从而保证外界组件可以被内部组件的信号触发。
    connect(ui->forget_label, &ClickedLabel::clicked, this, &LoginDialog::slot_forget_pwd);

    ui->err_Tips->clear();


    connect(ui->email_edit,&QLineEdit::editingFinished,this,[this](){
        checkEmailValid();
    });
    connect(ui->pass_edit,&QLineEdit::editingFinished,this,[this](){
        checkPassValid();
    });

    initHanler();

    //绑定下http的模块处理部分,信号会负责传输所有的参数过i来
    connect(HttpMgr::GetInstance().get(),&HttpMgr::sig_login_mod_finish,this,&LoginDialog::slot_login_mod_finish);

    //绑定我的connect与tcpMgr的操哈桑农户
    connect(this,&LoginDialog::sig_connect_tcp,TCPMgr::GetInstance().get(),&TCPMgr::solt_tcp_connect);


}

LoginDialog::~LoginDialog()
{
    delete ui;
}

void LoginDialog::slot_forget_pwd()
{
    qDebug()<<"slot forget pwd";
    emit switchReset();
}

bool LoginDialog::checkEmailValid()
{

    //验证邮箱的地址正则表达式
    auto email = ui->email_edit->text();
    // 邮箱地址的正则表达式
    QRegularExpression regex(R"((\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+)");
    bool match = regex.match(email).hasMatch(); // 执行正则表达式匹配
    if(!match){
        //提示邮箱不正确
        AddTipErr(TipErr::TIP_EMAIL_ERR, tr("邮箱地址不正确"));
        return false;
    }

    DelTipErr(TipErr::TIP_EMAIL_ERR);
    return true;
}

bool LoginDialog::checkPassValid()
{
    auto pass = ui->pass_edit->text();

    if(pass.length() < 6 || pass.length()>15){
        //提示长度不准确
        AddTipErr(TipErr::TIP_PWD_ERR, tr("密码长度应为6~15"));
        return false;
    }

    // 创建一个正则表达式对象，按照上述密码要求
    // 这个正则表达式解释：
    // ^[a-zA-Z0-9!@#$%^&*]{6,15}$ 密码长度至少6，可以是字母、数字和特定的特殊字符
    QRegularExpression regExp("^[a-zA-Z0-9!@#$%^&*]{6,15}$");
    bool match = regExp.match(pass).hasMatch();
    if(!match){
        //提示字符非法
        AddTipErr(TipErr::TIP_PWD_ERR, tr("不能包含非法字符"));
        return false;
    }

    DelTipErr(TipErr::TIP_PWD_ERR);

    return true;

}

void LoginDialog::AddTipErr(TipErr errid, QString str)
{
    //进行错误提示
    ShowTips(str,false);
    err_text.insert(errid,str);


}

void LoginDialog::DelTipErr(TipErr errid)
{
    err_text.remove(errid);
    if(err_text.empty())
    {
        //清除显示
        ui->err_Tips->clear();
        return;
    }
    ShowTips(err_text.first(),false);

}

//展示错误信息
void LoginDialog::ShowTips(QString ss, bool match)
{
    if(match)
    {
        ui->err_Tips->setText(ss);
        ui->err_Tips->setProperty("state","normal");
    }
    else
    {
        ui->err_Tips->setText(ss);
        ui->err_Tips->setProperty("state","err");
    }
    repolish(ui->err_Tips);
}

bool LoginDialog::checkAllValid()
{
    if(ui->email_edit->text()==""||ui->pass_edit->text()=="")
    {
        return false;
    }
    else
    {
        return true;
    }
}


//发送到这个模块时，这个魔窟啊会处理的布冯，待会还要发送到ID进行处理
void LoginDialog::slot_login_mod_finish(ReqId id, QString res, ErrorCodes err)
{

    //这里要重新梳理下，这里的错误信息，可以重新看一看是多少，服务端会把error信息带过i来的

    if(err != ErrorCodes::SUCCESS){

        //在这里进行处理，处理模块的消息，这则就是看是什么错误？
        //我觉得这个职责应该交给Reqid去做
        ShowTips(tr("网络请求错误"),false);
        return;
    }

    // 解析 JSON 字符串,res需转化为QByteArray
    QJsonDocument jsonDoc = QJsonDocument::fromJson(res.toUtf8());
    //json解析错误
    if(jsonDoc.isNull()){
        ShowTips(tr("json解析错误"),false);
        return;
    }

    //json解析错误
    if(!jsonDoc.isObject()){
        ShowTips(tr("json解析错误"),false);
        return;
    }

    QJsonObject jsonObj = jsonDoc.object();
    _map_function[id](jsonObj);


}

void LoginDialog::initHanler()
{

    //加入一个函数对象,函数对象接受一个参数jsonObj
    _map_function.insert(ReqId::ID_LOGIN,[this](const QJsonObject& jsobj){
        //处理一些事，在这进行处理
        if(jsobj["error"]!=ErrorCodes::SUCCESS)
        {
            if(jsobj["error"]==ErrorCodes::PasswdInvalid)
            {
                ShowTips(tr("密码错误"),false);
                return;
            }
            ShowTips(tr("参数错误"),false);
            return;
        }
        else
        {
            auto email = jsobj["email"].toString();
            ShowTips(tr("登陆成功"), true);

            //在这里解析所有的参数，然后使用socket的connect
            //可以使用信号传递，调用发送的槽函数，槽函数中继续发送调用
            ServerInfo si;
            si.Uid=jsobj["uid"].toInt();
            si.Port=jsobj["port"].toString();
            si.Host=jsobj["host"].toString();
            si.Token=jsobj["token"].toString();

            //调用TcpMgr的连接函数
            emit sig_connect_tcp(si);
            qDebug()<< "email is " << email ;
            return;
        }
    });

}

//post消息到后端
void LoginDialog::on_login_button_clicked()
{

    if(checkAllValid())
    {
        //无空输入，检查是否有错误
        if(err_text.empty())
        {
            //封装json数据，准备发送
            QJsonObject json_obj;
            json_obj["email"] = ui->email_edit->text();
            json_obj["passwd"] = ui->pass_edit->text();


            HttpMgr::GetInstance()->PostHttpreq(QUrl(gate_url_prefix+"/user_login"),json_obj,ReqId::ID_LOGIN,Modules::LOGINMOD);
            return;
        }
        else
        {
            //有错误输入
            ShowTips(err_text.first()+"，输入错误",false);
            return;
        }
    }
    else
    {

        //有空输入
        //有错误输入
        ShowTips("有空输入",false);
        return;
    }


}

